package net.mgsx.product.t2m.modisco.impact;
import java.util.ArrayList;
import java.util.Collection;

import net.mgsx.product.t2m.modisco.tools.ModiscoUtils;

import org.eclipse.gmt.modisco.java.ASTNode;
import org.eclipse.gmt.modisco.java.AbstractTypeDeclaration;
import org.eclipse.gmt.modisco.java.CompilationUnit;
import org.eclipse.gmt.modisco.java.TypeAccess;
import org.eclipse.gmt.modisco.infra.query.core.exception.ModelQueryExecutionException;
import org.eclipse.gmt.modisco.infra.query.core.java.IJavaModelQuery;
import org.eclipse.gmt.modisco.infra.query.core.java.ParameterValueList;

public class GetImpactedNodes implements IJavaModelQuery<ASTNode, Collection<ASTNode>> {
	public Collection<ASTNode> evaluate(final ASTNode context, final ParameterValueList parameterValues)
			throws ModelQueryExecutionException 
	{
		Collection<ASTNode> results = new ArrayList<ASTNode>();
		evaluateRecursive(context, results);
		if(context != null)
		{
			results.remove(context);
		}
		return results;
	}
	
	private void evaluateRecursive(final ASTNode context, final Collection<ASTNode> impactedNodes)
	{
		if(context == null)
		{
			ModiscoUtils.getLogger().logWarning("unknown impacted nodes for null node");
		}
		else if(!impactedNodes.contains(context))
		{
			impactedNodes.add(context);
			if(context instanceof CompilationUnit)
			{
				for(AbstractTypeDeclaration declaration : ((CompilationUnit) context).getTypes())
				{
					evaluateRecursive(declaration, impactedNodes);
				}
			}
			if(context instanceof AbstractTypeDeclaration)
			{
				for(TypeAccess declaration : ((AbstractTypeDeclaration) context).getUsagesInTypeAccess())
				{
					evaluateRecursive((AbstractTypeDeclaration)ModiscoUtils.getOwner(declaration, AbstractTypeDeclaration.class), impactedNodes);
				}
			}
			else
			{
				ModiscoUtils.getLogger().logWarning("unknown weight for " + context.eClass().getName());
			}
		}
	}
}
